package com.baiyue.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baiyue.enums.RoleEnum;
import com.baomidou.mybatisplus.plugins.Page;
import com.baiyue.entity.UserEntity;
import com.baiyue.exception.GlobalException;
import com.baiyue.mapper.UserMapper;
import com.baiyue.model.SelectOptionsResult;
import com.baiyue.model.user.LoginDataRequest;
import com.baiyue.model.user.UserInfoDataRequest;
import com.baiyue.model.user.UserInfoDataResponse;
import com.baiyue.result.CodeMsg;
import com.baiyue.service.UserService;
import com.baiyue.utils.BeanMapperUtil;
import com.baiyue.utils.Md5Util;
import com.baiyue.utils.RedisUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * @author WuBo
 */
@Service
@Slf4j
public class UserServiceImpl implements UserService {
    public static final String COOKIE_NAME_TOKEN = "token";

    private final String SAME_SITE_ATTRIBUTE_VALUES = ";Secure;SameSite=None";
    /**
     * token过期时间，2天
     */
    public static final int TOKEN_EXPIRE = 3600 * 24 * 2;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private HttpServletResponse response;

    @Autowired
    private Md5Util md5Util;
    /**
     * 根据Id查询
     *
     * @param request
     * @return
     */
    @Override
    public UserInfoDataResponse findById(UserInfoDataRequest request) {
        UserEntity userInfo = userMapper.selectById(request.getId());
        return BeanMapperUtil.map(userInfo,UserInfoDataResponse.class);
    }

    public UserEntity findById(Integer id){
        return userMapper.selectById(id);
    }

    /**
     * 根据用户名查询
     *
     * @param username
     * @return
     */
    @Override
    public UserEntity findByUsername(String username) {
        return userMapper.findByUsername(username);
    }

    /**
     * 获取token
     * @param response
     * @param token
     * @return
     */
    public UserEntity getByToken(HttpServletResponse response, String token) {
        if (StringUtils.isEmpty(token)) {
            return null;
        }
        UserEntity user = JSON.parseObject(redisUtil.get(COOKIE_NAME_TOKEN + "::" + token), UserEntity.class);
        //重置有效期
        if (user == null) {
            throw new GlobalException(CodeMsg.USER_NOT_LOGIN);
        }
        if (response != null) {
            addCookie(response, token, user);
        }
        return user;
    }

    public UserEntity getByToken(String token) {
        return getByToken(null, token);
    }

    private void addCookie(HttpServletResponse response, String token, UserEntity user) {
        //将token存入到redis
        redisUtil.set(COOKIE_NAME_TOKEN + "::" + token, JSON.toJSONString(user), TOKEN_EXPIRE);
        //将token写入cookie
        Cookie cookie = new Cookie(COOKIE_NAME_TOKEN, token);
        cookie.setMaxAge(TOKEN_EXPIRE);
        cookie.setPath("/");
        response.addCookie(cookie);
    }

    /**
     * 获得当前登录用户
     *
     * @param request
     * @return
     */
    @Override
    public UserEntity getLoginUser(HttpServletRequest request) {
        return getLoginUser(request, null);
    }

    /**
     * 获得当前登录用户
     *
     * @param request
     * @param response
     * @return
     */
    @Override
    public UserEntity getLoginUser(HttpServletRequest request, HttpServletResponse response) {

        String paramToken = request.getParameter(UserServiceImpl.COOKIE_NAME_TOKEN);
        String cookieToken = getCookieValue(request);


        if (StringUtils.isEmpty(cookieToken) && StringUtils.isEmpty(paramToken)) {
            // return null;
            throw new GlobalException(CodeMsg.USER_NOT_LOGIN);
        }
        String token = StringUtils.isEmpty(paramToken) ? cookieToken : paramToken;

        if (response == null) {
            return getByToken(token);
        }

        return getByToken(response, token);
    }



    /**
     * 分页查询用户列表
     * @param request 查询信息
     * @return 返回json
     */
    @Override
    public Page<UserInfoDataResponse> findAll(UserInfoDataRequest request) {
        log.info("查询用户列表入参：{}",JSON.toJSONString(request));
        Page<UserInfoDataResponse> pageable = new Page<>(request.getPage(),request.getSize());
        new UserEntity();
        UserEntity userDo = BeanMapperUtil.map(request,UserEntity.class);
        List<UserEntity> list = userMapper.findAll(userDo,pageable);
        List<UserInfoDataResponse> result = BeanMapperUtil.mapList(list,UserInfoDataResponse.class);
        for (int i = 0; i < result.size(); i++) {
            result.get(i).setPassword(null);
            result.get(i).setUserType(RoleEnum.getRoleEnum(list.get(i).getNickname()).getValue());
        }
        return pageable.setRecords(result);
    }

    /**
     * 查询状态为3（已删除）的用户
     * @param page
     * @param userEntity
     * @return
     */
    @Override
    public Page<UserEntity> findDelStatusUser(Page<UserEntity> page, UserEntity userEntity) {
        this.getLoginUser(request);
        if (userEntity.getStart() != null && !userEntity.getStart().isEmpty()){
            userEntity.setStart(userEntity.getStart()+" 00:00:00");
        }
        if (userEntity.getEnd() != null && !userEntity.getEnd().isEmpty()){
            userEntity.setEnd(userEntity.getEnd()+" 23:59:59");
        }
        return page.setRecords(userMapper.findDelStatusUser(userEntity.getUsername(),
                userEntity.getStart(),userEntity.getEnd(),userEntity.getSortField(),
                userEntity.getSortValue(),page));
    }

    /**
     * 查询用户列表 不分页
     * @return 返回List
     */
    @Override
    public List<UserEntity> findAll() {
        return userMapper.selectList(null);
    }

    /**
     * 添加用户
     * @param user 用户
     */
    @SneakyThrows
    @Override
    public void insert(UserInfoDataRequest user) {
        log.info("新增用户入参:{}", JSONObject.toJSONString(user));
        //判断用户是否存在
        UserEntity userEntity = findByUsername(user.getUsername());
        if (userEntity != null) {
            throw new GlobalException(CodeMsg.USERNAME_ALREADY_EXISTS);
        }
        UserEntity getUser = getLoginUser(request);
        String username = getUser.getUsername();
        user.setPassword(md5Util.encryptDES(user.getPassword()));
        UserEntity insertUser = BeanMapperUtil.map(user,UserEntity.class);
        insertUser.setCreatedBy(username);
        insertUser.setCreatedTime(new Date());
        insertUser.setUpdatedBy(username);
        insertUser.setUpdatedTime(new Date());
        insertUser.setMenuIds(String.valueOf(user.getMenuIds()));
        userMapper.insert(insertUser);
    }

    /**
     * 根据id 删除
     *
     * @param request 从request获取IDS
     */
    @Override
    public void deleteById(UserInfoDataRequest request) {
        log.info("删除用户入参Ids：{}",JSON.toJSONString(request.getIds()));
        if (request.getIds().isEmpty()){
            log.error("删除用户入参为空");
            throw new GlobalException(CodeMsg.BIND_ERROR.fillArgs("ids"));
        }
        Integer username = userMapper.deleteUserAllById(request.getIds());
        log.info("删除用户结果：{}",username);
    }

    /**
     * 登录方法
     * @param request
     * @return
     */
    @Override
    public String login(LoginDataRequest request) {

        //判断是邮箱还是手机号的正则表达式
        String email = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$";
        String phone = "^[1][34578]\\d{9}$";
        UserEntity user = null;
        if (request.getUsername().matches(email)) {
            user = userMapper.findByEmail(request.getUsername());
        }else if (request.getUsername().matches(phone)) {
            user = userMapper.findByPhone(request.getUsername());
        }else {
            user = findByUsername(request.getUsername());
        }
        if (Objects.isNull(user)) {
            throw new GlobalException(CodeMsg.USERNAME_NOT_EXIST);
        }

        if (user.getStatus()!=0){
            throw new GlobalException(CodeMsg.USERNAME_NOT_EXIST);
        }
        //验证密码，密码没有加密
        try {
            if (!md5Util.decryptDES(request.getPassword()).equals(md5Util.decryptDES(user.getPassword()))) {
                throw new GlobalException(CodeMsg.PASSWORD_ERROR);
            }
        } catch (Exception e) {
            log.error("UserService.login-解密或判断密码异常:{}",e.getMessage());
            throw new GlobalException(CodeMsg.PASSWORD_ERROR);
        }

        //生成cookie
        String token = UUID.randomUUID().toString().replace("-", "");
        addCookie(response, token, user);
        return token;
    }

    /**
     * 退出当前登录用户
     */
    @Override
    public void signOut() {
        Cookie[] cookies = request.getCookies();
        String token = "";
        for (Cookie cookie : cookies) {
            if (cookie.getName().equals("token")) {
                token = cookie.getValue();
            }
        }
        redisUtil.del("token::"+token);
    }

    /**
     * 获得当前用户cookie是否过期
     * 如没有过期，则直接登录
     * @return
     */
    @Override
    public void logged() {
        Cookie[] cookies = request.getCookies();
        String token = "";
        for (Cookie cookie : cookies) {
            if (cookie.getName().equals("token")) {
                token = cookie.getValue();
            }
        }
        String RedisToken = redisUtil.get("token::"+token);
        if (RedisToken == null || RedisToken.equals("")){
            throw new GlobalException(CodeMsg.COOKIE_IS_NOT_LOGIN);
        }
    }
    /**
     * 切换用户
     * @param username 用户名
     * @param password 密码
     * @return
     */
    @SneakyThrows
    @Override
    public String switchUser(String username, String password) {
        //判断用户名是否存在
        UserEntity user = findByUsername(username);
        if (user == null) {
            throw new GlobalException(CodeMsg.USERNAME_NOT_EXIST);
        }

        if (user.getStatus()!=0){
            throw new GlobalException(CodeMsg.USERNAME_NOT_EXIST);
        }

        //验证密码，密码没有加密
        String dbPass = md5Util.decryptDES(user.getPassword());
        if (!password.equals(dbPass)) {
            throw new GlobalException(CodeMsg.PASSWORD_ERROR);
        }

        Cookie[] cookies = request.getCookies();
        String token = "";
        for (Cookie cookie : cookies) {
            if (cookie.getName().equals("token")) {
                token = cookie.getValue();
            }
        }
        addCookie(response,token,user);
        return token;
    }

    /**
     * 修改用户
     * @param user
     */
    @SneakyThrows
    @Override
    public void update(UserInfoDataRequest user) {
        //判断用户是否存在
        UserEntity userEntity = userMapper.findByUser(user.getUsername());
        if (userEntity != null) {
            throw new GlobalException(CodeMsg.USERNAME_ALREADY_EXISTS);
        }
        UserEntity getUser = getLoginUser(request);
        String username = getUser.getUsername();
        if (!user.getPassword().equals("")){
            user.setPassword(md5Util.encryptDES(user.getPassword()));
        }
        UserEntity updateUser = BeanMapperUtil.map(user,UserEntity.class);
        updateUser.setUpdatedBy(username);
        updateUser.setUpdatedTime(new Date());
        if(!StringUtils.isEmpty(user.getMenuIds())){
            updateUser.setMenuIds(String.valueOf(user.getMenuIds()));
        }
        String key = redisUtil.findByUsernameOrId(updateUser.getUsername());
        if (!StringUtils.isEmpty(key)){
            redisUtil.del(key);
        }
        userMapper.updateById(updateUser);

    }

    /**
     * 更新用户时间
     * @param id
     */
    public void updateTime(Long[] id){
        Date updateTime = new Date();
        userMapper.updateTime(id,updateTime);

    }

    /**
     * 更新用户状态
     * @param id
     * @param status
     */
    @Override
    public void updateStatus(Integer id, Integer status) {
        UserEntity user = new UserEntity();
        user.setId(id);
        user.setStatus(status);
        userMapper.updateById(user);
    }



    /**
     * 拿到cookie 的值
     *
     * @param request
     * @return
     */
    private String getCookieValue(HttpServletRequest request) {
        Cookie[] cookies = request.getCookies();
        if (cookies == null || cookies.length == 0) {
            throw new GlobalException(CodeMsg.USER_NOT_LOGIN);
        }
        for (Cookie cookie : cookies) {
            if (cookie.getName().equals(UserServiceImpl.COOKIE_NAME_TOKEN)) {
                return cookie.getValue();
            }
        }
        return null;
    }

    @Override
    public List<SelectOptionsResult> getUserAndId(){
        List<SelectOptionsResult> list = userMapper.findUserAndEmail();
        if(list.isEmpty()){
            log.warn("获取用户列表下拉框失败");
            return null;
        }
        return list;
    }

    @Override
    public List<String> batchEmailSelectById(List<Integer> ids){
        List<String> emailList = userMapper.batchSelectById(ids);
        if(emailList.isEmpty()){
            log.warn("根据id获取用户邮箱失败");
            return null;
        }
        return emailList;
    }

    @Override
    public Integer deleteByEmail(String email){
        return userMapper.deleteByEmail(email);
    }
}
